﻿using System;

namespace CNG
{
    /// <summary>
    /// Thread-Safe Non-repetitive Random Number Generator
    /// </summary>
    /// <remarks>it's recommended to have a 64-bit cpu with more then 2GB ram</remarks>
    public sealed class ThreadSafeRandom : IDisposable
    {
        public ThreadSafeRandom(int Seed, int Max)
        {
            (Seed == int.MinValue).Require<ArgumentException>("Seed cannot be int.MinValue");

            (Max < 2).Require<ArgumentOutOfRangeException>("Max must be above 2 for this to work");

            random = new Random(Seed);
            size = left = Max;

            K = new bool[size];
        }

        private Random random;
        private volatile bool[] K;

        int size, left;

        /// <summary>
        /// returns the next random interger
        /// </summary>
        /// <returns>
        /// if there are not more random nambers left
        /// then it will return int.MinValue
        /// </returns>
        public int Next()
        {
            if (left == 0) return int.MinValue;
            int n;

            lock (random)
            {
                do n = random.Next(size);
                while (K[n]);
            }

            K[n] = true;

            left--;
            return n;
        }

        void IDisposable.Dispose()
        {
            K = null; random = null;
            GC.SuppressFinalize(this);
            GC.Collect();
        }
    }
}
